package top.jiangqiang.qianyi.common.exception;

import lombok.Getter;
import org.dromara.hutool.core.text.StrUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.web.server.ResponseStatusException;
import top.jiangqiang.qianyi.common.base.http.BaseStatus;

/**
 * 所有异常的基础类
 *
 * @author Jiangqiang
 * @version 1.0
 * @date 2023/3/14 8:53
 */
@Getter
public abstract class BaseException extends ResponseStatusException {

    /**
     * 业务编码，http状态码+对应错误枚举中的编码
     */
    protected final Integer businessCode;
    /**
     * 异常提示
     */
    protected final String message;
    protected final BaseStatus baseStatus;

    /**
     * @param baseStatus 错误枚举
     */
    public BaseException(BaseStatus baseStatus) {
        super(baseStatus.getHttpStatus(), baseStatus.getMessage());
        this.businessCode = baseStatus.getBusinessCode();
        this.message = super.getReason();
        this.baseStatus = baseStatus;
    }

    /**
     * @param baseStatus 错误枚举
     * @param cause      异常
     */
    public BaseException(BaseStatus baseStatus, Throwable cause) {
        super(baseStatus.getHttpStatus(), baseStatus.getMessage(), cause);
        this.businessCode = baseStatus.getBusinessCode();
        this.message = super.getReason();
        this.baseStatus = baseStatus;
    }

    /**
     * @param baseStatus 错误枚举
     * @param reason     错误原因
     * @param params     参数，用于填充reason中的占位符
     */
    public BaseException(BaseStatus baseStatus, String reason, Object... params) {
        super(baseStatus.getHttpStatus(), processMessage(baseStatus, reason, params));
        this.businessCode = baseStatus.getBusinessCode();
        this.message = super.getReason();
        this.baseStatus = baseStatus;
    }

    /**
     * @param baseStatus 错误枚举
     * @param reason     错误原因
     * @param cause      异常
     * @param params     参数，用于填充reason中的占位符
     */
    public BaseException(BaseStatus baseStatus, String reason, Throwable cause, Object... params) {
        super(baseStatus.getHttpStatus(), processMessage(baseStatus, reason, params), cause);
        this.businessCode = baseStatus.getBusinessCode();
        this.message = super.getReason();
        this.baseStatus = baseStatus;
    }

    /**
     * 处理message，reason优先级最高，如果为空则获取baseStatus的message
     *
     * @param baseStatus 错误枚举
     * @param reason     错误原因
     * @param params     参数，用于填充reason中的占位符
     */
    private static String processMessage(@NotNull BaseStatus baseStatus, String reason, Object... params) {
        if (StrUtil.isBlank(reason)) {
            return baseStatus.getMessage();
        }
        String message = StrUtil.format(reason, params);
        if (StrUtil.isBlank(message)) {
            return baseStatus.getMessage();
        } else {
            return message;
        }
    }
}
